package lg.iu.transforms;

import java.util.Iterator;

import lg.iu.ClassHooks;
import lg.iu.FieldHooks;

import org.objectweb.asm.Opcodes;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.FieldNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.MethodNode;

import wolf.iu.framework.ClassContainer;
import wolf.iu.framework.ClassesHandler;
import wolf.iu.framework.HooksList;
import wolf.iu.framework.hooks.AbstractTransform;
import wolf.iu.framework.hooks.HookState;
import wolf.iu.framework.insn.AnalyzerFactory;
import wolf.iu.framework.insn.InsnAnalyzer;
import wolf.iu.framework.insn.InstructionSearcher;

public class ClientScriptTransform extends AbstractTransform implements Opcodes {

    public boolean canRun(final ClassNode cn) {
        //if (!cn.name.equals("wfa"))
         //   return false;
        final Iterator<MethodNode> methods = cn.methods.iterator();
        while (methods.hasNext()) {
            final MethodNode method = methods.next();
            if (method.desc.equals("(IZ)V") && (method.access & ACC_PRIVATE) != 0) {
                if (new InstructionSearcher(method).getNextInt(SIPUSH, 1001) == null)
                    return false;
                return true;
            }
        }
        return false;
    }
    
    @Override
    public HookState execute(final ClassesHandler ch, final ClassContainer cc,
            final HooksList hooks) {
        
        if (!canRun(cc.getNode()))
            return HookState.WrongClass;
        
        System.out.println("running in " + cc.getSimpleName());
        
        hooks.setClassHook(ClassHooks.ClientScript, cc);
        
        final Iterator<MethodNode> methods = cc.getNode().methods.iterator();
        while (methods.hasNext()) {
            final MethodNode method = methods.next();
            final InstructionSearcher searcher = new InstructionSearcher(method);
            
            if ((method.access & Opcodes.ACC_STATIC) != 0 && method.desc.equals("(IZ)V")) {
                
                /*
                 *  XXX Interface transforms
                 */
                
                IntInsnNode iin = searcher.getNextInt(SIPUSH, 1001);
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.Width, fin);
                    }
                    fin = (FieldInsnNode) searcher
                    .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.Height, fin);
                    }
                }
                iin = searcher.getNextInt(SIPUSH, 1003);
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_Z);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.IsHidden, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1100));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.HScroll, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.MaxHScroll, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.MinHScroll, fin);
                    }
                    searcher.getNext(AnalyzerFactory.GETFIELD_I);
                    searcher.getNext(AnalyzerFactory.GETFIELD_I);
                    searcher.getNext(AnalyzerFactory.GETFIELD_I);
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.VScroll, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.MaxVScroll, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.MinVScroll, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1101));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.TextColor, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1105));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.TextureId, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1108));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ModelType, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ModelId, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1109));
                if (iin != null) {
                    searcher.getNext(AnalyzerFactory.PUTFIELD_I);
                    searcher.getNext(AnalyzerFactory.PUTFIELD_I);
                    FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ModelRotationX, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ModelRotationY, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ModelRotationZ, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ModelZoom, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1112));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_String);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.Text, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1115));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_Z);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.IsInventoryInterface, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1116));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.BorderThickness, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1117));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ShadowColor, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1118));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_Z);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.FlippedVertically, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1119));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_Z);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.FlippedHorizontally, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1305));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_String);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ItemName, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1306));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_String);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.SelectedActionName, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1307));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.PUTFIELD_StringA);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ItemActions, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1500));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.InventoryX, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1501));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.InventoryY, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1505));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ParentId, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1701));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ItemId, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ItemStackSize, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 1702));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Interface, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Interface, FieldHooks.ItemIndex, fin);
                    }
                }
                
                /*
                 * XXX Interface transforms ends
                 * 
                 * XXX Player transforms begins
                 */
                
                searcher.reset();
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 403));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_L);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Player, ch.getClass(fin.owner));
                        hooks.setClassHook(ClassHooks.PlayerDef, ch.getClass(fin.desc));
                        hooks.setFieldHook(ClassHooks.Player, FieldHooks.GetPlayerDef, fin);
                    }
                }
                
                // XXX skill hooks below
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3306));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getPrevious(AnalyzerFactory.GETSTATIC_IA);
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GetSkillLevels, fin);
                    }
                }
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3307));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getPrevious(AnalyzerFactory.GETSTATIC_IA);
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client,
                                FieldHooks.GetSkillLevelsMaxes, fin);
                    }
                }
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3308));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) searcher
                    .getPrevious(AnalyzerFactory.GETSTATIC_IA);
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GetSkillExperiences, fin);
                    }
                    
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETSTATIC_L);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Player, ch.getClass(fin.desc));
                        // client.add("localPlayer", fin); handled by
                        // ClientTransforms
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_B);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Animable, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Animable, FieldHooks.Plane, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Animable, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Animable, FieldHooks.AnimableX, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Animable, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.Animable, FieldHooks.AnimableY, fin);
                    }
                }
                
                /*
                 * XXX Player transforms ends
                 * 
                 * XXX World transform begins
                 */
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3318));
                if (iin != null) {
                    final FieldInsnNode numberNode = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    final FieldInsnNode worldNode = (FieldInsnNode) numberNode
                            .getPrevious();
                    if (worldNode != null) {
                        hooks.setClassHook(ClassHooks.World, ch.getClass(worldNode.desc));
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GetWorld, worldNode);
                    }
                    if (numberNode != null) {
                        hooks.setClassHook(ClassHooks.World, ch.getClass(numberNode.desc));
                        hooks.setFieldHook(ClassHooks.World, FieldHooks.WorldId, numberNode);
                    }
                }
                
                /*
                 * XXX World transform ends
                 * 
                 * XXX Player name transform begins
                 */
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3624));
                if (iin != null && hooks.containsHook(ClassHooks.Player)) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(new InsnAnalyzer() {
                                @Override
                                public boolean accept(final AbstractInsnNode ain) {
                                    if (ain instanceof FieldInsnNode) {
                                        final FieldInsnNode fin = (FieldInsnNode) ain;
                                        if (fin.owner.equals(hooks
                                                .getHook(ClassHooks.Player).getFullOldName())
                                                && fin.desc
                                                        .equals("Ljava/lang/String;"))
                                            return true;
                                    }
                                    return false;
                                }
                            });
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Player, FieldHooks.PlayerName, fin);
                    }
                }
                
                /*
                 * XXX Player name transform ends
                 * 
                 * XXX Model transform begins
                 */
                /*
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3760));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getPrevious(new InsnAnalyzer() {
                                @Override
                                public boolean accept(final AbstractInsnNode ain) {
                                    if (ain instanceof FieldInsnNode) {
                                        final FieldInsnNode fin = (FieldInsnNode) ain;
                                        if (fin.desc.contains("(IZI)V"))
                                            return true;
                                    }
                                    return false;
                                }
                            });
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.Model, ch.getClass(fin.owner));
                    }
                }
                TODO
                */
                
                /*
                 * XXX Model transform ends
                 * 
                 * XXX ItemDef transforms begin
                 */
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 4206));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        //System.out.println("Found ideftid");
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.CertTemplateId, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.CertId, fin);
                    }
                }

                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 4207));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_Z);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.IsMembers, fin);
                    }
                }
                
                /*
                 * XXX ItemDef transforms end
                 * 
                 * XXX MyCountry and GeItems transforms begin
                 */
                
                searcher.reset();
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3629));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETSTATIC_I); // TODO used another GETSTATIC_I
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.MyCountry, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3903));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETSTATIC_LA);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.GEItem, ch.getClass(fin.desc));
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GEItems, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3904));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.GEItem, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.GEItem, FieldHooks.GEItemId, fin);
                    }
                    fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.GEItem, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.GEItem, FieldHooks.Price, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3906));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.GEItem, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.GEItem, FieldHooks.Total, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3907));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.GEItem, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.GEItem, FieldHooks.Transfered, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 3908));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.GEItem, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.GEItem, FieldHooks.Spent, fin);
                    }
                }
                
                /*
                 * XXX MyCountry and GeItems transforms end
                 * 
                 * XXX ItemDef transforms begin
                 */
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 4200));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_String);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.ItemDefName, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 4201));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_StringA);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.GroundActions, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 4202));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_StringA);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.Actions, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 4203));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.Value, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 4204));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETFIELD_I);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDef, ch.getClass(fin.owner));
                        hooks.setFieldHook(ClassHooks.ItemDef, FieldHooks.Stackable, fin);
                    }
                }
                
                /*
                 * XXX ItemDef transforms end
                 * 
                 * XXX Random static transforms begin
                 */
                
                searcher.reset();
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 5009));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETSTATIC_I);
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.MyPlayerRights, fin);
                    }
                }
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 5401));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETSTATIC_L);
                    if (fin != null) {
                        hooks.setClassHook(ClassHooks.ItemDefLoader, ch.getClass(fin.desc));
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GetItemDefLoader, fin);
                    }
                }
                
                // XXX minimapAngle hook below
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 5507));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getPrevious(AnalyzerFactory.GETSTATIC_F);
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GetMinimapAngle, fin);
                    }
                }
                
                // XXX minimapSetting hook below
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 5700));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getPrevious(AnalyzerFactory.GETSTATIC_I);
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GetMinimapSetting, fin);
                    }
                }
                
                iin = (IntInsnNode) searcher.getNext(AnalyzerFactory
                        .makeIntCond(SIPUSH, 6509));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher
                            .getNext(AnalyzerFactory.GETSTATIC_I);
                    if (fin != null) {
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GameState, fin);
                    }
                }
                searcher.reset();
            }
            else if (method.desc.matches("\\(L[a-z]{1,3};I\\)V")) {
                final IntInsnNode iin = searcher.getNextInt(BIPUSH, 27);
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) searcher.getPrevious(AnalyzerFactory.GETSTATIC_L);
                    if (fin != null) {
                        final ClassNode settingClass = ch.getClass(fin.desc);
                        
                        hooks.setClassHook(ClassHooks.SettingData, settingClass);
                        hooks.setFieldHook(ClassHooks.Client, FieldHooks.GetSettingData, fin);
                        
                        for (final Object o : settingClass.fields) {
                            final FieldNode fn = (FieldNode) o;
                            if ((fn.access & Opcodes.ACC_PRIVATE) == 0) {
                                hooks.setFieldHook(ClassHooks.SettingData, FieldHooks.GetData,
                                        new FieldInsnNode(Opcodes.GETFIELD, settingClass.name, fn.name, fn.desc));
                                break;
                            }
                        }
                    }
                }
                //System.out.println(method.name + ">><<");
            }
            
        }
        
        return HookState.Found;
    }

}
